﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using WAF.Data;

namespace EntityTools
{
    public partial class FormMain : Form
    {
        private string oldFile = "";
        private string bakFile = "";

        public FormMain()
        {
            InitializeComponent();
        }

        private void FormMain_Load(object sender, EventArgs e)
        {
            //读取上一次使用的信息
            string historyFile = "history";

            if (File.Exists(historyFile))
            {
                StreamReader historySR = new StreamReader(historyFile, Encoding.Default);
                txtDBFile.Text = historySR.ReadLine();
                txtEntityFile.Text = historySR.ReadLine();
                historySR.Close();
            }
        }

        private void btnOpenDBFile_Click(object sender, EventArgs e)
        {
            openFileDialog.Filter = "SQLite数据库文件(*.db)|*.db|所有文件(*.*)|*.*";
            openFileDialog.ShowDialog();
        }

        private void btnOpenEntityFile_Click(object sender, EventArgs e)
        {
            saveFileDialog.Filter = "实体类文件(*.cs)|*.cs|所有文件(*.*)|*.*";
            saveFileDialog.ShowDialog();
        }

        private void openFileDialog_FileOk(object sender, CancelEventArgs e)
        {
            txtDBFile.Text = openFileDialog.FileName.Trim();
        }

        private void saveFileDialog_FileOk(object sender, CancelEventArgs e)
        {
            txtEntityFile.Text = saveFileDialog.FileName.Trim();
        }

        private void btnOK_Click(object sender, EventArgs e)
        {
            /*
            DbAccess.DbType = DbAccess.DatabaseType.SQLITE;
            DbAccess.ConnectionString = "Data Source=" + txtDBFile.Text;

            string s = WAF.Data.DbAccess.ExeScalar("select sql from sqlite_master where type='table' and name='Account'").ToString();
            MessageBox.Show(s);
            return;
            */
            oldFile = txtEntityFile.Text;

            if (oldFile == "")
            {
                MessageBox.Show("请指定一个数据库文件！");
                return;
            }

            //复制原有实体类文件，以便读取原有描述信息
            if (File.Exists(oldFile))
            {
                bakFile = oldFile + ".bak";
                File.Copy(oldFile, bakFile, true);
            }

            DbAccess.DbType = DbAccess.DatabaseType.SQLITE;
            DbAccess.ConnectionString = "Data Source=" + txtDBFile.Text;

            writeFile();

            //保存上一次使用的信息
            StreamWriter historySW = new StreamWriter("history", false, Encoding.Default);
            historySW.WriteLine(txtDBFile.Text);
            historySW.WriteLine(txtEntityFile.Text);
            historySW.Close();
        }

        //写实体类文件
        private void writeFile()
        {
            //生成新的实体类文件，如果已经存在则覆盖
            StreamWriter sw = new StreamWriter(txtEntityFile.Text, false, Encoding.Default);

            //名称空间开始
            sw.WriteLine("using System;");
            sw.WriteLine("using System.Data;");
            sw.WriteLine("using WAF.Data;");
            sw.WriteLine("");
            sw.WriteLine("namespace WAF.Data.EntityClass");
            sw.WriteLine("{");

            //获取表
            string tableSQL = "select name from sqlite_master where type='table' order by name";
            DataTable tb = DbAccess.ExeDataSet(tableSQL).Tables[0];

            string tbname = "";
            StringBuilder sb = new StringBuilder();

            foreach (DataRow row in tb.Rows)
            {
                //表名
                tbname = row[0].ToString();
                string tbSchema = DbAccess.ExeScalar("select sql from sqlite_master where type='table' and name='" + tbname + "'").ToString();

                int startIndex = tbSchema.IndexOf('(');
                int endIndex = tbSchema.LastIndexOf(')');
                string[] fieldSql = tbSchema.Substring(startIndex + 1, endIndex - startIndex - 1).Split(',');

                //类开头
                sw.WriteLine("  public class " + tbname + " : WAF.Data.EntityBase");
                sw.WriteLine("  {");

                //rowid字段信息
                sw.WriteLine("     [EntityFieldAttribute(0, true, true, true, false, DbType.Int64, 0, \"id\")]");
                sw.WriteLine("     public int rowid { get; set; }");
                sw.WriteLine();

                //字段顺序
                int sequence = 1;

                //其它字段信息
                foreach (DataRow rowFiled in getTableFieldInfo(tbname).Rows)
                {
                    string fieldName = rowFiled["name"].ToString().Trim();
                    string sharptype, dbtype, fieldSize, isUnique, isNotNull, isForeignKey, relTable, relIdField, relNameField;

                    //获取字段信息
                    getDbTypeString(rowFiled["type"].ToString(), out sharptype, out dbtype);
                    getFieldAttribute(fieldSql, fieldName, out fieldSize, out isUnique, out isNotNull, out isForeignKey, out relTable, out relIdField, out relNameField);

                    //属性
                    sb.Clear();
                    sb.Append("     [EntityFieldAttribute(")
                      .Append(sequence++).Append(", ")              //字段顺序
                      .Append("false, ")                            //是否主键
                      .Append(isUnique).Append(", ")                //是否唯一
                      .Append(isNotNull).Append(", ")               //是否可空
                      .Append(isForeignKey).Append(", ")            //是否外键
                      .Append(dbtype).Append(", ")                  //数据类型
                      .Append(fieldSize).Append(", ")               //字段长度
                      .Append(getDescription(tbname, fieldName));   //字段描述

                    //关联表信息
                    if( relTable != "" )
                    {
                      sb.Append(", ")
                        .Append(relTable).Append(", ")
                        .Append(relIdField).Append(", ")
                        .Append(relNameField);
                    }
                    
                    sb.Append(")]");
                    sw.WriteLine(sb.ToString());

                    //字段名
                    sb.Clear();
                    sb.Append("     public ").Append(sharptype).Append(" ").Append(fieldName).Append(" { get; set; }");
                    sw.WriteLine(sb.ToString());

                    sw.WriteLine();
                }

                //类结束
                sw.WriteLine("  }");
                sw.WriteLine();
            }

            //名称空间结尾
            sw.WriteLine("}");

            sw.Close();
            MessageBox.Show("生成成功！");
        }

        //获取字段原有的描述信息
        private string getDescription(string className, string fieldName)
        {
            //如果没有原有实体类文件则跳过搜索
            if (bakFile == "") return "";

            //读取原有实体类文件的拷贝文件以获取描述信息
            StreamReader sr = new StreamReader(bakFile, Encoding.Default);

            string description = "";
            string preLine = "";

            //是否是该类的成员
            bool isThisClass = false;

            while (!sr.EndOfStream)
            {
                string line = sr.ReadLine();

                if (line.IndexOf("class " + className) > 0)
                {
                    isThisClass = true;
                }
                else if (isThisClass && line.IndexOf(" " + fieldName + " ") > 0 && preLine.IndexOf('"') > 0)
                {
                    int startIndex = preLine.IndexOf('"');
                    int endIndex   = preLine.Remove(startIndex, 1).IndexOf('"') + 2;

                    description = preLine.Substring(startIndex, endIndex - startIndex);
                    break;
                }
                else
                {
                    preLine = line;
                }
            }

            sr.Close();
            return description;
        }

        //获取表信息，并添加主键rowid列（自增长）
        private DataTable getTableFieldInfo(string tbname)
        {
            string sql = "pragma table_info(" + tbname + ")";
            return DbAccess.ExeDataSet(sql).Tables[0];
        }

        //获取字段类型
        private void getDbTypeString(string sqlitetype, out string sharptype, out string dbtype)
        {
            sharptype = "";
            dbtype = "";

            switch (sqlitetype.ToUpper())
            {
                case "INT":
                    sharptype = "int";
                    dbtype = "DbType.Int32";
                    break;
                case "INTEGER":
                    sharptype = "long";
                    dbtype = "DbType.Int64";
                    break;
                case "FLOAT":
                    sharptype = "float";
                    dbtype = "DbType.Double";
                    break;
                case "DOUBLE":
                    sharptype = "double";
                    dbtype = "DbType.Double";
                    break;
                case "TEXT":
                    sharptype = "string";
                    dbtype = "DbType.String";
                    break;
                default:
                    sharptype = "string";
                    dbtype = "DbType.String";
                    break;
            }
        }

        //获取字段属性
        private void getFieldAttribute(string[] fieldSql, string fieldName, out string fieldSize, out string isUnique, out string isNotNull, out string isForeignKey, out string relTable, out string relIdField, out string relNameField)
        {
            fieldSize       = "0";
            isUnique        = "false";
            isNotNull       = "false";
            isForeignKey    = "false";
            relTable        = "";
            relIdField      = "";
            relNameField    = "";

            foreach (string ss in fieldSql)
            {
                string s = ss.Trim();

                //只能是开头的字段名匹配
                if (s.Trim().IndexOf(fieldName) == 1)
                {
                    //是否唯一
                    if (s.IndexOf(" UNIQUE") != -1)   isUnique = "true";
                    
                    //是否非空
                    if (s.IndexOf(" NOT NULL") != -1) isNotNull = "true";
                    
                    //字符型字段长度
                    if (s.IndexOf(" CHAR(1)") != -1) 
                        fieldSize = "1";
                    else if (s.IndexOf(" TEXT(") != -1)
                    {
                        int sIndex = s.IndexOf('(');
                        int eIndex = s.IndexOf(')');
                        fieldSize = s.Substring(sIndex + 1, eIndex - sIndex - 1);
                    }

                    //是否外键
                    if (s.IndexOf(" REFERENCES ") != -1)
                    {
                        string pattern = @"(\[\w+\])+";
                        MatchCollection matchs = Regex.Matches(s, pattern);

                        isForeignKey = "true";
                        relTable     = matchs[2].Value.Replace("[", "\"").Replace("]", "\"");
                        relIdField   = matchs[3].Value.Replace("[", "\"").Replace("]", "\"");
                        relNameField = matchs[1].Value.Replace("[", "\"").Replace("]", "\"");
                    }
                }
            }
        }
    }
}
